import asyncio
import json
import logging
import os
import queue
import random
import re
import threading

import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFilter, ImageFont
from aiogram import types
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types import InputFile, ParseMode
from barcode import Code39
from barcode.writer import ImageWriter

import client
import client_kb
import sqlite_db
from common_utils import compare_date, paste_watermark
from create_bot import BASE_DIR, dp
from handlers.users.generate.it_country.country_menu import create_italy

logger = logging.getLogger(__name__)


def process_generate_signature(user_id, data):
    text = data.capitalize()
    txt = Image.new("RGBA", (1900, 600), (255, 255, 255, 0))
    go_txt = ImageDraw.Draw(txt)
    fnt1 = ImageFont.truetype(f"./fonts/1.ttf", size=270)
    go_txt.text(xy=(200, 50), text=f"{text}", font=fnt1, fill="#000000")
    fnt2 = ImageFont.truetype(f"./fonts/2.ttf", size=190)
    go_txt.text(xy=(800, 50), text=f"{text}", font=fnt2, fill="#000000", stroke_width=1)
    fnt3 = ImageFont.truetype(f"./fonts/3.ttf", size=200)
    go_txt.text(
        xy=(1400, 50), text=f"{text}", font=fnt3, fill="#000000", stroke_width=1
    )
    fnt4 = ImageFont.truetype(f"./fonts/4.ttf", size=100)
    go_txt.text(
        xy=(200, 400), text=f"{text}", font=fnt4, fill="#000000", stroke_width=1
    )
    fnt5 = ImageFont.truetype(f"./fonts/5.ttf", size=150)
    go_txt.text(
        xy=(800, 400), text=f"{text}", font=fnt5, fill="#000000", stroke_width=1
    )
    fnt6 = ImageFont.truetype(f"./fonts/6.ttf", size=80)
    go_txt.text(xy=(1400, 400), text=f"{text}", font=fnt6, fill="#000000")
    fnt66 = ImageFont.truetype(f"./fonts/66.ttf", size=80)
    go_txt.text(xy=(1430, 440), text=f"k", font=fnt66, fill="#000000")
    txt_blur = txt.filter(ImageFilter.GaussianBlur(radius=1))
    holst = Image.new("RGBA", (1900, 600), (255, 255, 255, 255))
    choose_signature = Image.alpha_composite(holst, txt_blur)
    choose_signature.save(f"./files/it_id/photo_usr/{user_id}_choose_signature.png")


def process_passport_photo(user_id):
    try:
        # Load the image and face detection classifier
        img = cv2.imread(f"./files/it_id/photo_usr/{user_id}.png", cv2.IMREAD_UNCHANGED)
        face_cascade = cv2.CascadeClassifier(
            f"./data/haarcascade_frontalface_default.xml"
        )

        # Detect faces in the image
        faces = face_cascade.detectMultiScale(img, 1.2, 5)

        # If faces are detected, crop and resize the image
        if len(faces) != 0:
            (x, y, w, h) = faces[0]
            h_top = int(h * 0.4)
            h_bottom = int(h * 0.3)
            w_left = int(w * 0.2)
            w_right = int(w * 0.2)
            x_left = max(0, x - w_left)
            x_right = min(img.shape[1], x + w + w_right)
            w_new = x_right - x_left
            y_top = max(0, y - h_top)
            y_bottom = min(img.shape[0], y + h + h_bottom)
            h_new = y_bottom - y_top

            cropped_img = img[y_top : y_top + h_new, x_left : x_left + w_new]
            cropped_img_pil = Image.fromarray(
                cv2.cvtColor(cropped_img, cv2.COLOR_BGRA2RGBA)
            )

            # Resize the image proportionally to the width of 264px
            target_width = 264
            width_ratio = target_width / cropped_img_pil.width
            new_width = target_width
            new_height = int(cropped_img_pil.height * width_ratio)
            resized_width = cropped_img_pil.resize(
                (new_width, new_height), Image.ANTIALIAS
            )

            # Resize the image proportionally to the height of 345px
            target_height = 320
            height_ratio = target_height / resized_width.height
            new_height = target_height
            new_width = int(resized_width.width * height_ratio)
            resized_height = resized_width.resize(
                (new_width, new_height), Image.ANTIALIAS
            )

            # Center crop the image to get the width of 264px
            left = (resized_height.width - target_width) / 2
            top = 0
            right = (resized_height.width + target_width) / 2
            bottom = new_height
            cropped_resized = resized_height.crop((left, top, right, bottom))

            # Convert the image to grayscale and keep the alpha channel
            grayscale_img = cropped_resized.convert("LA").convert("RGBA")
            grayscale_img.putalpha(cropped_resized.getchannel("A"))

            # Save the processed image with the alpha channel
            grayscale_img.save(f"./files/it_id/photo_usr/{user_id}_w.png")
            os.remove(f"./files/it_id/photo_usr/{user_id}.png")
        else:
            print(f"No faces found in image for user_id {user_id}")
    except Exception as e:
        print(f"Error processing passport photo for user_id {user_id}: {str(e)}")


class FSM(StatesGroup):
    id_first_name = State()
    id_last_name = State()
    id_client_sex = State()
    id_birth_date = State()
    id_birth_place = State()
    id_client_id = State()
    id_client_can = State()
    id_client_fiscale = State()
    id_client_house = State()
    id_client_street = State()
    id_client_emission_date = State()
    id_client_emission_city = State()
    id_client_holo_id = State()
    id_client_signature_id = State()
    id_client_photo = State()
    id_size = State()
    id_edit_data = State()


data_fields = [
    {"title": "Имя", "key": "client_first_name"},
    {"title": "Фамилия", "key": "client_last_name"},
    {"title": "Пол", "key": "client_sex"},
    {"title": "Дата рождения", "key": "client_birth_date"},
    {"title": "Город рождения", "key": "client_birth_place"},
    {"title": "Номер ID", "key": "client_id"},
    {"title": "Номер CAN", "key": "client_can"},
    {"title": "Фискальный код", "key": "client_fiscale"},
    {"title": "Номер дома", "key": "client_house"},
    {"title": "Улица", "key": "client_street"},
    {"title": "Дата выдачи", "key": "client_emission_date"},
    {"title": "Город выдачи", "key": "client_emission_city"},
    {"title": "Голограмма", "key": "client_holo_id"},
    {"title": "Подпись", "key": "client_signature_id"},
    {"title": "Фотография", "key": "client_photo"},
    {"title": "Размер документа", "key": "size"},
]

back_kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
back_button = types.KeyboardButton(text="Назад ◀️")
back_button_inline = types.InlineKeyboardButton(
    text="Назад ◀️", callback_data="Назад ◀️"
)
back_kb.add(back_button)


async def data_checkup(user_id: int, state: FSMContext):
    try:
        data = await state.get_data()
        checkup_text = "Данные клиента:\n"
        for field in data_fields:
            if field["key"] in data:
                checkup_text += f"✅{field['title']}: {data[field['key']]}\n"
            else:
                checkup_text += f"{field['title']}:\n"
        if "message_to_edit_id" in data:
            await dp.bot.delete_message(
                chat_id=user_id, message_id=data["message_to_edit_id"]
            )
        return (await dp.bot.send_message(chat_id=user_id, text=checkup_text))[
            "message_id"
        ]
    except:
        pass


async def delete_user_reply(user_id: int, message_id: int):
    try:
        await dp.bot.delete_message(chat_id=user_id, message_id=message_id)
    except Exception as e:
        logger.warning(f"Unable to delete user message: {e}")


@dp.message_handler(Text(equals="ID 🇮🇹"), state="*")
async def id_client_first_name_input(message: types.Message, state: FSMContext):
    logger.info(f"Пользователь {message.from_user.id} начал создание документа")
    await sqlite_db.sql_add_country_user(message.from_user.id, "it_id")
    await state.update_data(type="id")
    await dp.bot.send_photo(
        chat_id=message.from_user.id, photo=InputFile(f"./files/it_id/example.jpg")
    )
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await message.answer(
            "Введите имя✏️\n",
            parse_mode=ParseMode.HTML,
            reply_markup=back_kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_first_name.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_first_name
)
async def id_first_name_validate(message: types.Message, state: FSMContext):
    client_first_name = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if re.match("^[A-Za-z `]+$", message.text) is not None:
        client_first_name = message.text
    if client_first_name is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        question_message_id = (
            await message.answer(
                text="❌Введите имя в правильном формате.\n"
                "<i>Формат ввода: только латинские буквы.</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=back_kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл имя")
        await state.update_data(client_first_name=client_first_name.upper())
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_last_name_input(message, state)


async def id_client_last_name_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await message.answer(
            "Введите фамилию✏️\n", parse_mode=ParseMode.HTML, reply_markup=back_kb
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_last_name.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_last_name
)
async def id_client_first_name_validate(message: types.Message, state: FSMContext):
    client_last_name = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if re.match("^[A-Za-z `]+$", message.text) is not None:
        client_last_name = message.text
    if client_last_name is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        question_message_id = (
            await message.answer(
                text="❌Введите фамилию в правильном формате.\n"
                "<i>Формат ввода: только латинские буквы.</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=back_kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл фамилию")
        await state.update_data(client_last_name=client_last_name.upper())
        data["sign"] = client_last_name.capitalize()
        if len(data["sign"]) > 5:
            data["sign"] = data["sign"][: random.randint(3, 5)]
        await state.update_data(sign=data["sign"])
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_sex_input(message, state)


async def id_client_sex_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Мужской 🙎🏻‍♂️"))
    kb.add(types.KeyboardButton(text="Женский 🙍🏻‍♀️"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Выберите пол\n", parse_mode=ParseMode.HTML, reply_markup=kb
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_sex.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_sex
)
async def id_client_sex_validate(message: types.Message, state: FSMContext):
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Мужской 🙎🏻‍♂️":
        sex = "M"
    elif message.text == "Женский 🙍🏻‍♀️":
        sex = "F"
    else:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Мужской 🙎🏻‍♂️"))
        kb.add(types.KeyboardButton(text="Женский 🙍🏻‍♀️"))
        question_message_id = (
            await message.answer(
                text="❌Выберите пол через клавиатуру.\n",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        return await state.update_data(question_message_id=question_message_id)
    logger.info(f"Пользователь {message.from_user.id} ввёл пол")
    await state.update_data(client_sex=sex)
    if "edit_mode" in data:
        return await start_generate_edit(message.from_user.id, state)
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    await id_client_birth_date_input(message, state)


async def id_client_birth_date_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await message.answer(
            "Введите дату рождения✏️\n" "<i>Формат ввода: дд.мм.гггг</i>",
            parse_mode=ParseMode.HTML,
            reply_markup=back_kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_birth_date.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_birth_date
)
async def id_client_birth_date_validate(message: types.Message, state: FSMContext):
    client_birth_date = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if re.match(r"^\d{2}\.\d{2}\.\d{4}$", message.text) is not None:
        client_birth_date = message.text
    if client_birth_date is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        question_message_id = (
            await message.answer(
                text="❌Введите дату рождения в правильном формате.\n"
                "<i>Формат ввода: дд.мм.гггг</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=back_kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл дату рождения")
        await state.update_data(client_birth_date=client_birth_date)
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_birth_place_input(message, state)


async def id_client_birth_place_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Сгенерировать"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите город рождения и его короткое обозначение в скобках✏️\n"
            "<i>Пример: TORINO (TO)</i>\n",
            parse_mode=ParseMode.HTML,
            reply_markup=kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_birth_place.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_birth_place
)
async def id_client_birth_place_validate(message: types.Message, state: FSMContext):
    client_birth_place = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Сгенерировать":
        cities_array = [
            "TORINO (TO)",
            "VERCELLI (VC)",
            "NOVARA (NV)",
            "CUNEO (CN)",
            "ASTI (AT)",
            "ALESSANDRIA (AL)",
            "BIELLA (BI)",
            "VARESE (VA)",
            "COMO (CO)",
            "SONDRIO (SO)",
            "MILANO (MI)",
            "BERGAMO (BG)",
            "BRESCIA (BS)",
            "PAVIA (PV)",
            "CREMONA (CR)",
            "MANTOVA (MN)",
            "LECCO (LC)",
            "LODI (LO)",
            "TRENTO (TN)",
            "VERONA (VR)",
            "VICENZA (VI)",
            "BELLUNO (BL)",
            "TREVISO (TV)",
            "VENEZIA (VE)",
            "PADOVA (PD)",
            "ROVIGO (RO)",
        ]
        client_birth_place = random.choice(cities_array)
    elif re.match("^[A-Za-z\s]+\s\([A-Za-z]{2}\)$", message.text.upper()) is not None:
        client_birth_place = message.text
    if client_birth_place is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Сгенерировать"))
        question_message_id = (
            await message.answer(
                text="❌Введите город рождения и его короткое название в правильном формате.\n"
                "<i>Формат ввода: Название города и короткое обозначение в скобках, например MILANO (MI)</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл место рождения")
        await state.update_data(client_birth_place=client_birth_place.upper())
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_id_input(message, state)


async def id_client_id_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Сгенерировать"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите номер ID (5 цифр)✏️\n", parse_mode=ParseMode.HTML, reply_markup=kb
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_id.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_id
)
async def id_client_id_validate(message: types.Message, state: FSMContext):
    client_id = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Сгенерировать":
        client_id = str(random.randint(10000, 99999))
    elif re.match("^[0-9]{5}$", message.text) is not None:
        client_id = message.text

    if client_id is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Сгенерировать"))
        question_message_id = (
            await message.answer(
                text="❌Введите номер ID в правильном формате.\n"
                "<i>Формат ввода: 5 цифр</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл ID")
        await state.update_data(client_id=client_id)
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_can_input(message, state)


async def id_client_can_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Сгенерировать"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите номер CAN (6 цифр)✏️\n", parse_mode=ParseMode.HTML, reply_markup=kb
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_can.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_can
)
async def id_client_can_validate(message: types.Message, state: FSMContext):
    client_can = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Сгенерировать":
        client_can = str(random.randint(100000, 999999))
    elif re.match("^[0-9]{6}$", message.text) is not None:
        client_can = message.text

    if client_can is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Сгенерировать"))
        question_message_id = (
            await message.answer(
                text="❌Введите номер CAN в правильном формате.\n"
                "<i>Формат ввода: 6 цифр.</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл номер CAN")
        await state.update_data(client_can=client_can)
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_fiscale_input(message, state)


async def id_client_fiscale_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Сгенерировать"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите фискальный код✏️\n<i>Формат ввода: 16 символов, латинские буквы или цифры.</i>\nФормат: xxxxxxYYxYYxYYYx, x - буква, Y - цифра.",
            parse_mode=ParseMode.HTML,
            reply_markup=kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_fiscale.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_fiscale
)
async def id_client_fiscale_validate(message: types.Message, state: FSMContext):
    client_fiscale = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Сгенерировать":
        client_fiscale = "generate"
    elif re.match("^[A-Za-z0-9]{16}$", message.text) is not None:
        client_fiscale = message.text

    if client_fiscale is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Сгенерировать"))
        question_message_id = (
            await message.answer(
                text="❌Введите фискальный код в правильном формате.\n"
                "<i>Формат ввода: 16 символов, латинские буквы или цифры.</i>\n"
                "Формат: xxxxxxYYxYYxYYYx, x - буква, Y - цифра.",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл фискальный код")
        await state.update_data(client_fiscale=client_fiscale.upper())
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_house_input(message, state)


async def id_client_house_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Пропустить"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите номер дома✏️\n" "или нажмите пропустить",
            parse_mode=ParseMode.HTML,
            reply_markup=kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_house.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_house
)
async def id_client_house_validate(message: types.Message, state: FSMContext):
    client_house = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Пропустить":
        client_house = ""
    elif message.text.isdigit() and int(message.text) > 0:
        client_house = message.text

    if client_house is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Пропустить"))
        question_message_id = (
            await message.answer(
                text="❌Введите номер дома в правильном формате или нажмите пропустить.\n"
                "<i>Формат ввода: целое число больше 0.</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл номер дома")
        await state.update_data(client_house=client_house)
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_street_input(message, state)


async def id_client_street_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await message.answer(
            "Введите название улицы✏️\n",
            parse_mode=ParseMode.HTML,
            reply_markup=back_kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_street.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_street
)
async def id_client_street_validate(message: types.Message, state: FSMContext):
    client_street = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text is not None:
        client_street = message.text
    if client_street is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        question_message_id = (
            await message.answer(
                text="❌Введите название улицы в правильном формате.\n"
                "<i>Формат ввода: только латинские буквы и пробелы.</i>",
                parse_mode=ParseMode.HTML,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл улицу")
        await state.update_data(client_street=client_street.upper())
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_emission_date_input(message, state)


async def id_client_emission_date_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await message.answer(
            "Введите дату выдачи✏️\n"
            "<i>Формат ввода: дд.мм.гггг</i>\nДата не ранее 04.07.2016!",
            parse_mode=ParseMode.HTML,
            reply_markup=back_kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_emission_date.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_emission_date
)
async def id_client_emission_date_validate(message: types.Message, state: FSMContext):
    client_emission_date = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if re.match(r"^\d{2}\.\d{2}\.\d{4}$", message.text) is not None and compare_date(
        "04.07.2016", message.text
    ):
        client_emission_date = message.text
    if client_emission_date is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        question_message_id = (
            await message.answer(
                text="❌Введите дату выдачи в правильном формате.\n"
                "<i>Формат ввода: дд.мм.гггг</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=back_kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл дату выдачи")
        await state.update_data(client_emission_date=client_emission_date)
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_emission_city_input(message, state)


async def id_client_emission_city_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
    kb.add(types.KeyboardButton(text="Сгенерировать"))
    kb.add(back_button)
    question_message_id = (
        await message.answer(
            "Введите город выдачи✏️\n"
            "<i>Формат ввода: название города и его сокращённое название в скобках\n"
            "Пример: TORINO (TO).</i>",
            parse_mode=ParseMode.HTML,
            reply_markup=kb,
        )
    )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_emission_city.set()


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_emission_city
)
async def id_client_emission_city_validate(message: types.Message, state: FSMContext):
    client_emission_city = None
    await delete_user_reply(message.from_user.id, message.message_id)
    data = await state.get_data()

    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")

    if message.text == "Сгенерировать":
        cities_array = [
            "TORINO (TO)",
            "VERCELLI (VC)",
            "NOVARA (NV)",
            "CUNEO (CN)",
            "ASTI (AT)",
            "ALESSANDRIA (AL)",
            "BIELLA (BI)",
            "VARESE (VA)",
            "COMO (CO)",
            "SONDRIO (SO)",
            "MILANO (MI)",
            "BERGAMO (BG)",
            "BRESCIA (BS)",
            "PAVIA (PV)",
            "CREMONA (CR)",
            "MANTOVA (MN)",
            "LECCO (LC)",
            "LODI (LO)",
            "TRENTO (TN)",
            "VERONA (VR)",
            "VICENZA (VI)",
            "BELLUNO (BL)",
            "TREVISO (TV)",
            "VENEZIA (VE)",
            "PADOVA (PD)",
            "ROVIGO (RO)",
        ]
        client_emission_city = random.choice(cities_array)
    elif re.match("^[A-Za-z\s]+\s\([A-Z]{2}\)$", message.text.upper()) is not None:
        client_emission_city = message.text.upper()

    if client_emission_city is None:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="Сгенерировать"))
        question_message_id = (
            await message.answer(
                text="❌Введите город выдачи в правильном формате.\n"
                "<i>Формат ввода: название города и его сокращённое название в скобках\n"
                "Пример: TORINO (TO).</i>",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        await state.update_data(question_message_id=question_message_id)
    else:
        logger.info(f"Пользователь {message.from_user.id} ввёл город выдачи")
        await state.update_data(client_emission_city=client_emission_city.upper())
        if "edit_mode" in data:
            return await start_generate_edit(message.from_user.id, state)
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        await id_client_holo_id_input(message, state)


async def id_client_holo_id_input(message: types.Message, state: FSMContext):
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)

    kb = types.InlineKeyboardMarkup(resize_keyboard=True)
    kb.row(
        types.InlineKeyboardButton(text="1", callback_data="holo_1"),
        types.InlineKeyboardButton(text="2", callback_data="holo_2"),
        types.InlineKeyboardButton(text="3", callback_data="holo_3"),
        types.InlineKeyboardButton(text="4", callback_data="holo_4"),
    )
    kb.add(
        types.InlineKeyboardButton(text="Не ставить", callback_data="holo_0"),
        back_button_inline,
    )

    photo_path = (
        f"./files/it_id/source/holo_choice.png"  # Замените на путь к вашей картинке
    )
    with open(photo_path, "rb") as photo:
        question_message_id = (
            await message.answer_photo(
                photo, caption="Выберите номер голограммы:", reply_markup=kb
            )
        )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_holo_id.set()


@dp.callback_query_handler(
    lambda c: c.data.startswith("holo_") and "Назад ◀️" not in c.data,
    state=FSM.id_client_holo_id,
)
async def id_client_holo_id_validate(
    callback_query: types.CallbackQuery, state: FSMContext
):
    await dp.bot.answer_callback_query(callback_query.id)
    holo_id = int(callback_query.data.split("_")[1])
    logger.info(f"Пользователь {callback_query.from_user.id} выбрал голограмму")
    await state.update_data(client_holo_id=holo_id)

    data = await state.get_data()
    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=callback_query.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")
    if "edit_mode" in data:
        return await start_generate_edit(callback_query.from_user.id, state)
    message_to_edit_id = await data_checkup(callback_query.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    await id_client_signature_id_input(callback_query.from_user.id, state)


async def id_client_signature_id_input(user_id, state: FSMContext):
    if type(user_id) == types.Message:
        user_id = user_id.from_user.id
    message_to_edit_id = await data_checkup(user_id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    data = await state.get_data()

    process_generate_signature(user_id=user_id, data=data["sign"])

    kb = types.InlineKeyboardMarkup()
    kb.add(
        types.InlineKeyboardButton(text="1", callback_data="sig_1"),
        types.InlineKeyboardButton(text="2", callback_data="sig_2"),
        types.InlineKeyboardButton(text="3", callback_data="sig_3"),
    )
    kb.add(
        types.InlineKeyboardButton(text="4", callback_data="sig_4"),
        types.InlineKeyboardButton(text="5", callback_data="sig_5"),
        types.InlineKeyboardButton(text="6", callback_data="sig_6"),
    )
    kb.add(
        types.InlineKeyboardButton(text="Не ставить", callback_data="sig_0"),
        back_button_inline,
    )

    photo_path = f"./files/it_id/photo_usr/{user_id}_choose_signature.png"  # Замените на путь к вашей картинке
    with open(photo_path, "rb") as photo:
        question_message_id = (
            await dp.bot.send_photo(
                chat_id=user_id,
                photo=photo,
                caption="Выберите тип подписи:",
                reply_markup=kb,
            )
        )["message_id"]
    await state.update_data(question_message_id=question_message_id)
    await FSM.id_client_holo_id.set()


@dp.callback_query_handler(
    lambda c: c.data.startswith("sig_") and "Назад ◀️" not in c.data,
    state=FSM.id_client_holo_id,
)
async def id_client_signature_id_validate(
    callback_query: types.CallbackQuery, state: FSMContext
):
    await dp.bot.answer_callback_query(callback_query.id)
    signature_id = int(callback_query.data.split("_")[1])
    await state.update_data(client_signature_id=signature_id)
    logger.info(f"Пользователь {callback_query.from_user.id} выбрал подпись")
    data = await state.get_data()
    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=callback_query.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")
    if "edit_mode" in data:
        return await start_generate_edit(callback_query.from_user.id, state)
    message_to_edit_id = await data_checkup(callback_query.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    await id_client_photo_input(callback_query.from_user.id, state)


async def id_client_photo_input(user_id: int or types.Message, state: FSMContext):
    if type(user_id) == types.Message:
        user_id = user_id.from_user.id
    message_to_edit_id = await data_checkup(user_id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    question_message_id = (
        await dp.bot.send_message(
            chat_id=user_id,
            text="Загрузите фотографию 📷\n"
            " ❗️Требования к фотографии:\n"
            "➖ Фотография должна быть загружена без сжатия, нажимаем скрепку - файл - выбрать фото;\n"
            "➖ На фотографии должно быть видно плечи, глаза открыты;\n"
            "➖ Кадр должен быть в хорошем освещении;\n"
            "➖ Лицо должно быть под прямым углом к камере;\n"
            "Поддерживаемые форматы: JPG, JPEG, PNG ❗️",
            reply_markup=back_kb,
        )
    )["message_id"]
    await FSM.id_client_photo.set()
    await state.update_data(question_message_id=question_message_id)


@dp.message_handler(content_types=types.ContentType.DOCUMENT, state=FSM.id_client_photo)
async def process_photo(message: types.Message, state: FSMContext):
    data = await state.get_data()
    # Check if the message has a document
    # Check if the document is in the required format (PNG)
    file_info = await dp.bot.get_file(message.document.file_id)
    await message.delete()
    if file_info.file_path.lower().endswith(".png"):
        # Download the document and save it as user_id.png
        photo_path = f"./files/it_id/photo_usr/{message.from_user.id}.png"
        await dp.bot.download_file(file_info.file_path, photo_path)
        # Check if the image has an alpha channel
        img = Image.open(photo_path).convert("RGBA")
        if img.mode == "RGBA":
            # Process the photo in a separate thread
            thread = threading.Thread(
                target=process_passport_photo, args=(message.from_user.id,)
            )
            thread.start()
            # Проверка состояния потока каждую секунду с использованием asyncio.sleep
            while thread.is_alive():
                await asyncio.sleep(1)
            # Check if the processed photo exists
            processed_photo_path = (
                f"./files/it_id/photo_usr/{message.from_user.id}_w.png"
            )
            if os.path.exists(processed_photo_path):
                data = await state.get_data()
                question_message_id = data.get("question_message_id")
                try:
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=question_message_id
                    )
                    message_to_edit_id = await data_checkup(message.from_user.id, state)
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=message_to_edit_id
                    )
                except:
                    pass
                logger.info(f"Пользователь {message.from_user.id} отправил фотографию")
                await id_size_input(message, state)
    elif file_info.file_path.lower().endswith(".jpg"):
        # Download the document and save it as user_id.png
        photo_path = f"./files/it_id/photo_usr/{message.from_user.id}.png"
        await dp.bot.download_file(
            file_info.file_path, f"./files/it_id/photo_usr/{message.from_user.id}.jpg"
        )
        # AI work

        from rembg import remove

        out = remove(
            Image.open(f"./files/it_id/photo_usr/{message.from_user.id}.jpg"),
            True,
            240,
            240,
        )
        out = out.convert("RGBA")
        out.save(f"./files/it_id/photo_usr/{message.from_user.id}.png")
        # Check if the image has an alpha channel
        img = Image.open(photo_path).convert("RGBA")
        if img.mode == "RGBA":
            # Process the photo in a separate thread
            thread = threading.Thread(
                target=process_passport_photo, args=(message.from_user.id,)
            )
            thread.start()
            # Проверка состояния потока каждую секунду с использованием asyncio.sleep
            while thread.is_alive():
                await asyncio.sleep(1)
            # Check if the processed photo exists
            processed_photo_path = (
                f"./files/it_id/photo_usr/{message.from_user.id}_w.png"
            )
            if os.path.exists(processed_photo_path):
                data = await state.get_data()
                question_message_id = data.get("question_message_id")
                try:
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=question_message_id
                    )
                    message_to_edit_id = await data_checkup(message.from_user.id, state)
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=message_to_edit_id
                    )
                except:
                    pass
                logger.info(f"Пользователь {message.from_user.id} отправил фотографию")
                await id_size_input(message, state)
    elif file_info.file_path.lower().endswith(".jpeg"):
        # Download the document and save it as user_id.png
        photo_path = f"./files/it_id/photo_usr/{message.from_user.id}.png"
        await dp.bot.download_file(
            file_info.file_path, f"./files/it_id/photo_usr/{message.from_user.id}.jpeg"
        )
        # AI work

        from rembg import remove

        out = remove(
            Image.open(f"./files/it_id/photo_usr/{message.from_user.id}.jpeg"),
            True,
            240,
            240,
        )
        out = out.convert("RGBA")
        out.save(f"./files/it_id/photo_usr/{message.from_user.id}.png")
        # Check if the image has an alpha channel
        img = Image.open(photo_path).convert("RGBA")
        if img.mode == "RGBA":
            # Process the photo in a separate thread
            thread = threading.Thread(
                target=process_passport_photo, args=(message.from_user.id,)
            )
            thread.start()
            # Проверка состояния потока каждую секунду с использованием asyncio.sleep
            while thread.is_alive():
                await asyncio.sleep(1)
            # Check if the processed photo exists
            processed_photo_path = (
                f"./files/it_id/photo_usr/{message.from_user.id}_w.png"
            )
            if os.path.exists(processed_photo_path):
                data = await state.get_data()
                question_message_id = data.get("question_message_id")
                try:
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=question_message_id
                    )
                    message_to_edit_id = await data_checkup(message.from_user.id, state)
                    await dp.bot.delete_message(
                        chat_id=message.chat.id, message_id=message_to_edit_id
                    )
                except:
                    pass
                logger.info(f"Пользователь {message.from_user.id} отправил фотографию")
                await id_size_input(message, state)
            else:
                await dp.bot.send_message(
                    chat_id=message.chat.id,
                    text="❌ Фотография не соответствует требованиям.\n"
                    "ИИ не смог обработать вашу фотографию.\n"
                    "Это происходит, если фото не соответствует требованиям, "
                    "проверьте что расширение файла PNG, "
                    "либо загрузите другое изображение.",
                )
        else:
            await dp.bot.send_message(
                chat_id=message.chat.id,
                text="❌ Фотография не соответствует требованиям.\n"
                "ИИ не смог обработать вашу фотографию.\n"
                "Это происходит, если фото не соответствует требованиям, "
                "проверьте что расширение файла PNG, "
                "либо загрузите другое изображение.",
            )
    else:
        await dp.bot.send_message(
            chat_id=message.chat.id,
            text="❌ Фотография не соответствует требованиям.\n"
            "ИИ не смог обработать вашу фотографию.\n"
            "Это происходит, если фото не соответствует требованиям, "
            "проверьте что расширение файла PNG, "
            "либо загрузите другое изображение.",
        )


@dp.message_handler(
    lambda message: "Назад ◀️" not in message.text, state=FSM.id_client_photo
)
async def process_photo_nontype(message: types.Message, state: FSMContext):
    await message.delete()
    await message.answer(
        "Вы должны отправить фотографию без фона в формате PNG и без сжатия."
    )


@dp.message_handler(content_types=types.ContentType.PHOTO, state=FSM.id_client_photo)
async def process_photo_nontype_photo(message: types.Message, state: FSMContext):
    await message.delete()
    await message.answer(
        "Вы должны отправить фотографию без фона в формате PNG и без сжатия."
    )


async def id_size_input(user_id: int or types.Message, state: FSMContext):
    if type(user_id) == types.Message:
        user_id = user_id.from_user.id
    message_to_edit_id = await data_checkup(user_id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    kb = types.ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
    kb.add(types.KeyboardButton(text="📃На листе А4"))
    kb.add(types.KeyboardButton(text="🪪В размер документа"))
    kb.add(back_button)
    question_message_id = (
        await dp.bot.send_message(
            chat_id=user_id, text="Выберите размер документа", reply_markup=kb
        )
    )["message_id"]
    await FSM.id_size.set()
    await state.update_data(question_message_id=question_message_id)


@dp.message_handler(lambda message: "Назад ◀️" not in message.text, state=FSM.id_size)
async def id_select_size_validate(message: types.Message, state: FSMContext):
    if message.text == "📃На листе А4":
        size_type = "A4"
    elif message.text == "🪪В размер документа":
        size_type = "DOC"
    else:
        message_to_edit_id = await data_checkup(message.from_user.id, state)
        await state.update_data(message_to_edit_id=message_to_edit_id)
        kb = types.ReplyKeyboardMarkup(resize_keyboard=True)
        kb.add(types.KeyboardButton(text="📃На листе А4"))
        kb.add(types.KeyboardButton(text="🪪В размер документа"))
        question_message_id = (
            await message.answer(
                text="❌Выберите тип через клавиатуру.\n",
                parse_mode=ParseMode.HTML,
                reply_markup=kb,
            )
        )["message_id"]
        return await state.update_data(question_message_id=question_message_id)
    await message.delete()
    await state.update_data(size=size_type)
    logger.info(f"Пользователь {message.from_user.id} выбрал размер документа")
    data = await state.get_data()
    if "question_message_id" in data:
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=data["question_message_id"]
        )
    else:
        logger.warning("question_message_id not found in state data")
    if "edit_mode" in data:
        return await start_generate_edit(message.from_user.id, state)
    message_to_edit_id = await data_checkup(message.from_user.id, state)
    await state.update_data(message_to_edit_id=message_to_edit_id)
    await start_generate(message, state)


async def start_generate(message: types.Message, state: FSMContext):
    message_to_delete = await message.answer("Ожидайте генерируется...")
    data = await state.get_data()
    logger.info(f"Начинаем генерацию документа для пользователя {message.from_user.id}")
    result_queue = queue.Queue()
    id_thread = threading.Thread(
        target=generate_id, args=(data, message.from_user.id, result_queue)
    )
    id_thread.start()
    id_thread.join()
    result = result_queue.get()
    if "Error" in result:
        logger.error(
            f"Ошибка при генерации документа для пользователя {message.from_user.id}:\n{result}"
        )
        await message.answer("❌Ошибка при генерации изображения")
        await dp.bot.send_message(chat_id=363661148, text=result)
    else:
        logger.info(
            f"Успешно завершили генерацию документа для пользователя {message.from_user.id}"
        )
        await dp.bot.delete_message(
            chat_id=message.from_user.id, message_id=message_to_delete["message_id"]
        )
        with open(result + "_wm.png", "rb") as photo:
            await dp.bot.send_document(chat_id=message.from_user.id, document=photo)
            await message.answer(
                "Завершите покупку документа.", reply_markup=client_kb.kb_it_finish_id
            )


async def start_generate_edit(user_id: int, state: FSMContext):
    message_to_delete = await dp.bot.send_message(
        chat_id=user_id, text="Ожидайте генерируется..."
    )
    data = await state.get_data()
    result_queue = queue.Queue()
    id_thread = threading.Thread(target=generate_id, args=(data, user_id, result_queue))
    id_thread.start()
    id_thread.join()
    result = result_queue.get()
    if "Error" in result:
        await dp.bot.send_message(
            chat_id=user_id, text="❌Ошибка при генерации изображения"
        )
        await dp.bot.send_message(chat_id=363661148, text=result)
    else:
        await dp.bot.delete_message(
            chat_id=user_id, message_id=message_to_delete["message_id"]
        )
        with open(result + "_wm.png", "rb") as photo:
            await dp.bot.send_document(chat_id=user_id, document=photo)
            await dp.bot.send_message(
                chat_id=user_id,
                text="Завершите покупку документа.",
                reply_markup=client_kb.kb_it_finish_id,
            )


@dp.callback_query_handler(text="it_change_id", state="*")
async def it_change_id(call: types.CallbackQuery, state: FSMContext):
    kb = types.ReplyKeyboardMarkup(one_time_keyboard=True)
    await call.message.delete()
    for field in data_fields:
        kb.add(types.KeyboardButton(text=f'{field["title"]}'))
    edit_message_to_delete_id = (
        await call.message.answer(
            text="Выберите параметр, который хотите изменить", reply_markup=kb
        )
    )["message_id"]
    await state.update_data(edit_message_to_delete_id=edit_message_to_delete_id)
    await FSM.id_edit_data.set()


@dp.message_handler(state=FSM.id_edit_data)
async def edit_field(message: types.Message, state: FSMContext):
    data = await state.get_data()
    await dp.bot.delete_message(
        chat_id=message.from_user.id, message_id=int(data["edit_message_to_delete_id"])
    )
    await message.delete()
    for field in data_fields:
        if field["title"] == message.text:
            key = field["key"]
    await state.update_data(edit_mode=1)
    func_name = key
    func_name_with_input = "id_" + func_name + "_input"

    # Получаем ссылку на функцию с использованием имени и вызываем ее
    function_to_call = globals()[func_name_with_input]
    await function_to_call(message, state)


@dp.callback_query_handler(text="it_pay_id", state="*")
async def command_pay_it_bill(callback: types.CallbackQuery, state: FSMContext):
    await state.finish()
    await state.update_data(pay_country="it_id")
    await client.command_promo_quest(callback, state)


state_input_functions = {
    "FSM:id_first_name": create_italy,
    "FSM:id_last_name": id_client_first_name_input,
    "FSM:id_client_sex": id_client_last_name_input,
    "FSM:id_birth_date": id_client_sex_input,
    "FSM:id_birth_place": id_client_birth_date_input,
    "FSM:id_client_id": id_client_birth_place_input,
    "FSM:id_client_can": id_client_id_input,
    "FSM:id_client_fiscale": id_client_can_input,
    "FSM:id_client_house": id_client_fiscale_input,
    "FSM:id_client_street": id_client_house_input,
    "FSM:id_client_emission_date": id_client_street_input,
    "FSM:id_client_emission_city": id_client_emission_date_input,
    "FSM:id_client_holo_id": id_client_emission_city_input,
    "FSM:id_client_signature_id": id_client_holo_id_input,
    "FSM:id_client_photo": id_client_signature_id_input,
    "FSM:id_size": id_client_photo_input,
}


@dp.message_handler(lambda message: message.text == "Назад ◀️", state=FSM)
async def go_back(message: types.Message, state: FSMContext):
    current_state = str(await state.get_state())
    print(current_state)
    if current_state in state_input_functions:
        input_function = state_input_functions[current_state]
        await input_function(
            message, state
        )  # вызов функции ввода для предыдущего состояния
    else:
        await message.answer("Unknown state.")


@dp.callback_query_handler(lambda call: call.data == "Назад ◀️", state="*")
async def go_back(call: types.CallbackQuery, state: FSMContext):
    await call.message.delete()
    current_state = str(await state.get_state())
    if current_state in state_input_functions:
        input_function = state_input_functions[current_state]
        await input_function(
            call.message, state
        )  # вызов функции ввода для предыдущего состояния
    else:
        await call.message.answer("Unknown state.")


def generate_id(data, user_id, result_queue):
    try:
        import datetime
        import random

        import codicefiscale as codicefiscale
        from mrz.generator.td1 import TD1CodeGenerator
        from PIL import Image, ImageDraw, ImageEnhance, ImageFilter, ImageFont

        def get_adjusted_font_size(text, max_width, font_path, initial_font_size):
            font_size = initial_font_size
            font = ImageFont.truetype(font_path, font_size)
            text_width, _ = font.getsize(text)

            while text_width > max_width:
                font_size -= 1
                font = ImageFont.truetype(font_path, font_size)
                text_width, _ = font.getsize(text)

            return font_size

        # Загрузка исходного изображения
        image = Image.open(f"./files/it_id/source/template.png").convert("RGBA")
        # Создание объекта ImageDraw для рисования на изображении
        draw = ImageDraw.Draw(image)

        """
        Переменные текста
        """
        last_name = data["client_last_name"]
        first_name = data["client_first_name"]
        birth_city = data["client_birth_place"]

        birth_date = data["client_birth_date"]
        sex = data["client_sex"]
        height = random.randint(170, 185)
        issue_date = data["client_emission_date"]
        emisson_place = data["client_emission_city"]
        pattern = r"(\w+)\s+\((\w+)\)"
        match = re.search(pattern, emisson_place)
        emisson_place, emisson_place_short = match.groups()
        signature_id = data["client_signature_id"]
        expire_date_date = birth_date[:5]
        expire_date_year = datetime.datetime.strftime(
            datetime.datetime.strptime(issue_date, "%d.%m.%Y")
            + datetime.timedelta(days=365 * 10),
            "%Y",
        )

        CA_letter = f"CA          CM"
        CA_numbers = data["client_id"]
        ID = data["client_can"]
        holo_id = data["client_holo_id"]
        street = data["client_street"]
        house = data["client_house"]

        """
        Фискальный код
        """
        if data["client_fiscale"] == "GENERATE":
            birth_date_obj = datetime.datetime.strptime(birth_date, "%d.%m.%Y").date()
            pattern = r"(\w+)\s+\((\w+)\)"
            match = re.search(pattern, birth_city)
            city, city_short = match.groups()
            with open(f"./data/it_city_codes.json", "r") as f:
                # Загружаем данные из формата JSON
                codes_dict = json.load(f)
            birth_place = codes_dict[city]
            fiscale_code = codicefiscale.build(
                last_name, first_name, birth_date_obj, sex, birth_place
            )
        else:
            fiscale_code = data["client_fiscale"]

        # Рендер места выдачи
        font = ImageFont.truetype(f"./fonts/TitilliumWeb-SemiBold.ttf", 21)
        x, y = 204, 167
        draw.text(
            xy=(x, y),
            text=f"{emisson_place}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер фамилии
        font = ImageFont.truetype(f"./fonts/TitilliumWeb-SemiBold.ttf", 21)
        x, y = 330, 219
        draw.text(
            xy=(x, y),
            text=f"{last_name}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер имени
        x, y = 331, 263
        draw.text(
            xy=(x, y),
            text=f"{first_name}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер места и даты рождения
        x, y = 331, 321
        draw.text(
            xy=(x, y),
            text=f"{birth_city} {birth_date}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер пола
        x, y = 331, 376
        draw.text(
            xy=(x, y),
            text=f"{sex}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер роста
        x, y = 465, 376
        draw.text(
            xy=(x, y),
            text=f"{height}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер даты выдачи
        x, y = 331, 421
        draw.text(
            xy=(x, y),
            text=f"{issue_date}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер даты устаревания
        x, y = 623, 421
        draw.text(
            xy=(x, y),
            text=f"{expire_date_date}.{expire_date_year}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Генерация и рендер подписи
        sign = data["sign"].capitalize()
        if signature_id != 0:
            fonts_dict = {
                1: ImageFont.truetype(f"./fonts/1.ttf", size=90),
                2: ImageFont.truetype(f"./fonts/2.ttf", size=63),
                3: ImageFont.truetype(f"./fonts/3.ttf", size=90),
                4: ImageFont.truetype(f"./fonts/4.ttf", size=50),
                5: ImageFont.truetype(f"./fonts/5.ttf", size=75),
                6: ImageFont.truetype(f"./fonts/6.ttf", size=40),
                7: ImageFont.truetype(f"./fonts/66.ttf", size=30),
            }
            if signature_id == 6:
                font = fonts_dict[5]
                x, y = 331, 500
                txt = Image.new("RGBA", (1800, 600), (255, 255, 255, 0))
                go_txt = ImageDraw.Draw(txt)
                go_txt.text(
                    xy=(x, y),
                    text=sign,
                    font=font,
                    fill=(0, 0, 0, 250),
                    stroke_width=0,
                    anchor="lm",
                )
                fnt66 = ImageFont.truetype(f"./fonts/66.ttf", size=90)
                go_txt.text(
                    xy=(x + 25, y - 15), text=f"k", font=fonts_dict[7], fill="#000000"
                )
                txt_blur = txt.filter(ImageFilter.GaussianBlur(radius=0.5))
                # Создайте новый слой подписи с размером, соответствующим изображению документа
                signature_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))

                # Вставьте изображение подписи на слой подписи
                signature_position = (0, 0)  # координаты x, y для вставки подписи
                signature_layer.paste(txt_blur, signature_position)

                # Объедините изображение документа и слой подписи
                image = Image.alpha_composite(image, signature_layer)
            else:
                font = fonts_dict[signature_id]
                x, y = 331, 500
                txt = Image.new("RGBA", (1800, 600), (255, 255, 255, 0))
                go_txt = ImageDraw.Draw(txt)
                go_txt.text(
                    xy=(x, y),
                    text=sign,
                    font=font,
                    fill=(0, 0, 0, 250),
                    stroke_width=0,
                    anchor="lm",
                )
                txt_blur = txt.filter(ImageFilter.GaussianBlur(radius=0.5))
                # Создайте новый слой подписи с размером, соответствующим изображению документа
                signature_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))

                # Вставьте изображение подписи на слой подписи
                signature_position = (0, 0)  # координаты x, y для вставки подписи
                signature_layer.paste(txt_blur, signature_position)

                # Объедините изображение документа и слой подписи
                image = Image.alpha_composite(image, signature_layer)

        draw = ImageDraw.Draw(image)

        # Рендер CAxxx ID
        x, y = 706, 64
        font = ImageFont.truetype(f"./fonts/ITC Souvenir Greek Light.ttf", 30)
        draw.text(
            xy=(x, y),
            text=f"{CA_letter}",
            font=font,
            fill=(49, 52, 27, 255),
            stroke_width=0,
            anchor="lm",
        )
        font = ImageFont.truetype(f"./fonts/ITC Souvenir Greek Light.ttf", 28)
        draw.text(
            xy=(x + 47, y + 1),
            text=f"{CA_numbers}",
            font=font,
            fill=(49, 52, 27, 255),
            stroke_width=0,
            anchor="lm",
        )

        # Рендер ID
        font = ImageFont.truetype(f"./fonts/it_font_1.ttf", 32)
        x, y = 723, 455
        draw.text(
            xy=(x, y),
            text=f"{ID}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        def multiply_images(image1, image2):
            if image1.size != image2.size:
                logger.exception("Изображения должны быть одного размера")
                return None

            result_image = Image.new("RGBA", image1.size, (0, 0, 0, 0))
            for x in range(image1.width):
                for y in range(image1.height):
                    pixel1 = image1.getpixel((x, y))
                    pixel2 = image2.getpixel((x, y))
                    new_pixel = tuple(int(a * b / 255) for a, b in zip(pixel1, pixel2))
                    result_image.putpixel((x, y), new_pixel)

            return result_image

        # Вставка фотографии
        # 1. Откройте другое изображение
        overlay_image = Image.open(f"./files/it_id/photo_usr/{user_id}_w.png").convert(
            "RGBA"
        )

        overlay_position = (
            55,
            192,
        )  # координаты x, y для вставки обрезанного изображения
        overlay_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))
        overlay_layer.paste(overlay_image, overlay_position, overlay_image)

        # Используйте функцию multiply_images() для наложения overlay_image на image
        overlay_layer = multiply_images(image, overlay_layer)

        # Объедините исходное изображение и новый слой с помощью `Image.alpha_composite()`
        image = Image.alpha_composite(image, overlay_layer)

        """
        Вставка подписи под фото
        """
        result_text = f"{last_name}{first_name}CA{CA_numbers}CM" * 20
        # Создаем новое изображение для текста
        text_image = Image.new("RGBA", image.size, (255, 255, 255, 0))

        draw = ImageDraw.Draw(text_image)
        font = ImageFont.truetype(f"./fonts/TitilliumWeb-ExtraLight.ttf", 6)

        # Наносим текст на изображение
        draw.text(
            (46, 510),
            text=f"{result_text}",
            font=font,
            fill=(49, 52, 27, 255),
        )

        # Обрезаем изображение
        left = 0
        top = 0
        right = 325
        bottom = text_image.size[1]  # обрезаем только по ширине, сохраняем высоту
        cropped_text_image = text_image.crop((left, top, right, bottom))

        # Соединяем исходное изображение с обрезанным текстовым слоем
        image.paste(cropped_text_image, (0, 0), cropped_text_image)
        """
        Вставка голограмы
        """
        if holo_id != 0:
            overlay_image = Image.open(
                f"./files/it_id/source/holo{holo_id}.png"
            ).convert("RGBA")
            # # if holo_id == 2:
            # #     overlay_layer = lighten_images(image, overlay_image)
            # # else:
            # # Уменьшаем прозрачность overlay_image на 50%
            # overlay_image = apply_opacity(
            #     overlay_image, 127
            # )  # 127 = 50% прозрачности (255 * 0.5)
            # # Создаем новый слой для наложения overlay_image на image
            # overlay_layer = Image.new("RGBA", image.size, (0, 0, 0, 0))
            # overlay_layer.paste(overlay_image, (0, 0), overlay_image)

            # Объедините исходное изображение и новый слой с помощью `Image.alpha_composite()`
            image = Image.alpha_composite(image, overlay_image)

        """
                Вставка голограмы рамки фотографии
                """
        overlay_image = Image.open(
            f"./files/it_id/source/photo_holo_frame.png"
        ).convert("RGBA")

        # Измените размер overlay_image
        new_size = (280, 370)  # Замените width и height на нужные значения
        overlay_image = overlay_image.resize(new_size, Image.ANTIALIAS)

        # Задайте координаты для вставки overlay_image на image
        overlay_position = (40, 155)  # Замените x и y на нужные значения координат

        # Вставьте overlay_image на image с использованием альфа-канала
        image.paste(overlay_image, overlay_position, overlay_image)

        """
        MRZ-Code
        """
        draw = ImageDraw.Draw(image)
        # Задайте все необходимые данные
        document_type = "C"  # Тип документа для итальянской ID-карты
        country_code = "ITA"
        surname = last_name
        given_names = first_name
        document_number = f"CA{CA_numbers}CM"
        nationality = "ITA"

        # Исправлено: Преобразуем даты рождения и окончания срока действия в формат '%y%m%d'
        birth_date = datetime.datetime.strptime(birth_date, "%d.%m.%Y").strftime(
            "%y%m%d"
        )
        expire_date = expire_date_date + "." + expire_date_year
        expiry_date = datetime.datetime.strptime(expire_date, "%d.%m.%Y").strftime(
            "%y%m%d"
        )

        # Создайте генератор кода MRZ
        td1_generator = TD1CodeGenerator(
            document_type=document_type,
            country_code=country_code,
            document_number=document_number,
            birth_date=birth_date,
            sex=sex,
            expiry_date=expiry_date,
            nationality=nationality,
            surname=surname,
            given_names=given_names,
        )

        # Выведите сгенерированный код MRZ
        print(td1_generator)
        # Создайте отдельное изображение для текста
        text_image = Image.new("RGBA", image.size, (255, 255, 255, 0))

        # todo: Рендер кода на текстовом слое
        font = ImageFont.truetype(f"{BASE_DIR}/fonts/es_OCR-B 10 BT.ttf", 47)
        draw = ImageDraw.Draw(text_image)
        x, y = 1103, 500
        draw.text(
            xy=(x, y),
            text=f"{td1_generator}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
            spacing=10,
        )

        # Применяем размытие к текстовому слою
        blur_radius = 0.6  # Устанавливаем радиус размытия
        text_image = text_image.filter(ImageFilter.GaussianBlur(radius=blur_radius))

        # Объединяем текстовый слой с основным изображением
        image.alpha_composite(text_image)

        # Создайте штрих-код CODE128
        code128 = Code39(fiscale_code, writer=ImageWriter())
        code128.background = "#ffffff00"
        code128.save(f"{BASE_DIR}/files/it_id/photo_usr/{user_id}_barcode")

        # Откройте изображение и преобразуйте его в RGBA-формат
        barcode_image = Image.open(
            f"{BASE_DIR}/files/it_id/photo_usr/{user_id}_barcode.png"
        ).convert("RGBA")
        # Конвертируем изображение в массив numpy
        np_image = np.array(barcode_image)

        # Ищем все пиксели с белым цветом и заменяем их на прозрачный
        white = np.array([255, 255, 255, 255], dtype=np.uint8)
        mask = np.all(np_image == white, axis=-1)
        np_image[mask] = [0, 0, 0, 0]

        # Конвертируем массив numpy обратно в изображение PIL
        barcode_image = Image.fromarray(np_image, mode="RGBA")
        # Обрезаем изображение
        barcode_image = barcode_image.crop(
            (0, 0, barcode_image.width, barcode_image.height - 80)
        )

        # Изменяем размер изображения с сохранением исходного разрешения
        barcode_image = barcode_image.resize(
            (800, int(270 * barcode_image.height / barcode_image.width + 43))
        )
        # Вставляем изображение на основное изображение
        position = (1125, 275)
        barcode_image = barcode_image.filter(ImageFilter.GaussianBlur(radius=0.5))
        image.paste(barcode_image, position, mask=barcode_image)

        """
        Рендер фискального кода на 2 сторону
        """
        # Создайте отдельное изображение для текста
        text_image = Image.new("RGBA", image.size, (255, 255, 255, 0))
        draw = ImageDraw.Draw(text_image)
        font = ImageFont.truetype(f"{BASE_DIR}/fonts/TitilliumWeb-SemiBold.ttf", 20)
        x, y = 1127, 143
        draw.text(
            xy=(x, y),
            text=f"{fiscale_code}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )

        # Применяем размытие к текстовому слою
        blur_radius = 0.2  # Устанавливаем радиус размытия
        text_image = text_image.filter(ImageFilter.GaussianBlur(radius=blur_radius))

        # Объединяем текстовый слой с основным изображением
        image.alpha_composite(text_image)

        """
        Рендер адреса и города на второу сторону
        """
        # Создайте отдельное изображение для текста
        text_image = Image.new("RGBA", image.size, (255, 255, 255, 0))
        draw = ImageDraw.Draw(text_image)
        font = ImageFont.truetype(f"{BASE_DIR}/fonts/TitilliumWeb-SemiBold.ttf", 20)
        x, y = 1127, 187
        draw.text(
            xy=(x, y),
            text=f"{street}, {house} {birth_city}",
            font=font,
            fill=(49, 52, 27, 235),
            stroke_width=0,
            anchor="lm",
        )
        # Применяем размытие к текстовому слою
        blur_radius = 0.2  # Устанавливаем радиус размытия
        text_image = text_image.filter(ImageFilter.GaussianBlur(radius=blur_radius))

        # Объединяем текстовый слой с основным изображением
        image.alpha_composite(text_image)

        """
        Рендер ESTERMI ATTO DI NASCITA
        """
        # Создайте отдельное изображение для текста
        random_text = (
            "".join([f"{random.randint(0, 9)}" for _ in range(3)])
            + " "
            + f"{chr(random.randint(65, 90))}"
            + " "
            + f"{random.randint(0, 9)}"
            + " "
            + f"{chr(random.randint(65, 90))}"
            + " "
            + f"{chr(random.randint(65, 90))}"
        )
        text_image = Image.new("RGBA", image.size, (255, 255, 255, 0))
        draw = ImageDraw.Draw(text_image)
        font = ImageFont.truetype(f"{BASE_DIR}/fonts/TitilliumWeb-SemiBold.ttf", 20)
        x, y = 1499, 130
        draw.text(
            xy=(x, y),
            text=random_text,
            font=font,
            fill=(49, 52, 27, 255),
            stroke_width=0,
            anchor="lm",
        )

        # Применяем размытие к текстовому слою
        blur_radius = 0.2  # Устанавливаем радиус размытия
        text_image = text_image.filter(ImageFilter.GaussianBlur(radius=blur_radius))

        # Объединяем текстовый слой с основным изображением
        image.alpha_composite(text_image)

        """
        Маленькое изображение с уменьшеной прозрачностью
        """
        # 1. Откройте другое изображение
        overlay_image = Image.open(
            f"{BASE_DIR}/files/it_id/photo_usr/{user_id}_w.png"
        ).convert("RGBA")
        new_size = (int(overlay_image.width // 2.5), int(overlay_image.height // 2.5))
        overlay_image.thumbnail(new_size, resample=Image.LANCZOS)
        # Уменьшаем прозрачность вставленного изображения
        alpha = 180  # Значение прозрачности (0-255); 200 - чуть прозрачное
        alpha_channel = Image.new("L", overlay_image.size, alpha)
        overlay_image_alpha = Image.composite(
            alpha_channel, overlay_image.split()[3], overlay_image.split()[3]
        )
        overlay_image.putalpha(overlay_image_alpha)

        # 5. Создайте новый слой и вставьте на него обрезанное изображение
        overlay_position = (
            1829,
            95,
        )  # координаты x, y для вставки обрезанного изображения
        overlay_layer = Image.new("RGBA", image.size, (255, 255, 255, 0))
        overlay_layer.paste(overlay_image, overlay_position, overlay_image)

        # 6. Объедините исходное изображение и новый слой с помощью `Image.alpha_composite()`
        image = Image.alpha_composite(image, overlay_layer)
        image_name = f"./files/it_id/photo_usr/{user_id}_completed"
        if data["size"] == "DOC":
            # Сохранение полученного результата
            image.save(image_name + ".png")
        elif data["size"] == "A4":
            image.save(image_name + ".png")
            image = Image.open(image_name + ".png")
            white = Image.new("RGB", image.size, (255, 255, 255))
            white.paste(image, (0, 0), image)
            # Задаем размеры A4 в миллиметрах
            width_mm = 210
            height_mm = 297

            # Задаем разрешение изображения в DPI
            resolution_dpi = 600

            # Конвертируем размеры A4 в пиксели
            width_px = int(width_mm * resolution_dpi / 25.4)
            height_px = int(height_mm * resolution_dpi / 25.4)

            # Создаем новое изображение размером A4 с белым фоном
            image_a4 = Image.new("RGBA", (width_px, height_px), "white")
            new_width = 4400  # Задаем новую ширину в пикселях
            new_height = int(
                white.height * new_width / white.width
            )  # Вычисляем новую высоту, сохраняя соотношение сторон
            white = white.resize((new_width, new_height), Image.ANTIALIAS)
            image_a4.paste(white, (150, 150))

            # Сохраняем изображение в файл
            image_a4.save(image_name + ".png", "PNG")
        else:
            raise ValueError

        paste_watermark(
            f"./files/it_id/photo_usr/{user_id}_completed.png",
            f"./files/it_id/photo_usr/{user_id}_completed_wm.png",
        )

        result_queue.put(image_name)
    except KeyError as _ex:
        print(_ex)
        result_queue.put(f"Error:Ошибка в предоставленных данных:\n")
    except ValueError as _ex:
        print(_ex)
        result_queue.put(f"Error:Ошибка при сохранении результата:\n")
    except Exception as _ex:
        print(_ex)
        result_queue.put(f"Error:Ошибка при генерации:\n")
